﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml.Linq;

namespace MikeKappel.Com.Uploader
{
    /// <summary>
    /// Summary description for ServerControl1
    /// </summary>
    [ToolboxData("<{0}:Uploader runat=\"server\"></{0}:Uploader>")]
    public class Uploader : Panel, IScriptControl
    {
        private ScriptManager sm;
        private HtmlGenericControl iframe;
        private UploaderInfo uploader;
 
        private Guid InternalID
        {
            get
            {
                if (ViewState["ID"] == null)
                    ViewState["ID"] = Guid.NewGuid();

                return (Guid)ViewState["ID"];
            }
            set
            {
                ViewState["ID"] = value;
            }
        }
        public String AllowedMimes
        {
            get
            {
                return String.Concat(uploader.MimesExcepted);
            }
            set
            {
                if (String.IsNullOrEmpty(value) || !value.Contains(","))
                    uploader.MimesExcepted = new String[]{value};
                else
                    uploader.MimesExcepted = value.Split(',');
            }
        }
        public Int32? MaxSize
        {
            get
            {
                return uploader.MaxSize;
            }
            set
            {
                uploader.MaxSize = value;
            }
        }
        public String Name
        {
            set
            {
                uploader.Name = value;
            }
        }
        /// <summary>
        /// CSS that will be loaded into the inner iframe.
        /// </summary>
        public String CssInnerUrl
        {
            set
            {
                 uploader.CssUrlInner = value;
            }
        }

        /// <summary>
        /// CSS that will be loaded into the main page.
        /// </summary>
        public String CssOuterUrl
        {
            get;
            set;
        }

        /// <summary>
        /// Text to display for changing image.
        /// </summary>
        public String TextForImageChange
        {
            set
            {
                uploader.TextForImageChange = value;
            }
        }

        /// <summary>
        /// Text to notify user upload it too large
        /// Must contain {0} for Max file size to be displayed
        /// </summary>
        public String TextForOversize
        {
            set
            {
                uploader.TextForOversize = value;
            }
        }

        /// <summary>
        /// Text  to notify user of unsupported file type
        /// Must contain {0} for attempted file type to be displayed
        /// </summary>
        public String TextForUnsupported
        {
            set
            {
                uploader.TextForUnsupported = value;
            }
        }
        
        /// <summary>
        /// Text to notify user upload cancelled
        /// </summary>
        public String TextForCancelled
        {
            get;
            set;
        }
        public  UploaderEventArgs.UploadComplete OnUploadComplete{
            get{
                return uploader.OnUploadComplete;
            }
            set{
                uploader.OnUploadComplete = value;
            }
        }
        protected override void OnInit(EventArgs e)
        {
            uploader = Core.GetUploader(InternalID);
            if (uploader == null)
            {
                uploader = new UploaderInfo(InternalID, ClientID);
                Core.SetUploader(uploader);
            }
            base.OnInit(e);
        }
        protected override void OnPreRender(EventArgs e)
        {
            if (!this.DesignMode)
            {
                sm = ScriptManager.GetCurrent(Page);

                if (sm == null)
                    throw new HttpException("A ScriptManager control must exist on the current page.");

                sm.RegisterScriptControl(this);
            }

            base.OnPreRender(e);

            if (String.IsNullOrEmpty(uploader.CssUrlInner))
                uploader.CssUrlInner = Page.ClientScript.GetWebResourceUrl(this.GetType(), "MikeKappel.Com.DefaultInnerStyle.css");

            ScriptManager.RegisterClientScriptBlock(this.Page, typeof(System.Web.UI.Control), "_calcss", String.Format(Core.CssFileHtml, this.CssOuterUrl), false);
            iframe.Attributes.Add("src", CurrentFrameUrl());

            if (String.IsNullOrEmpty(uploader.TextForImageChange))
                uploader.TextForImageChange = "Change Image";

            if (String.IsNullOrEmpty(uploader.TextForUnsupported))
                uploader.TextForUnsupported = "Unsupported file type {0}";

            if (String.IsNullOrEmpty(uploader.TextForOversize))
                uploader.TextForOversize = "Please slect a file less then {0}MB";

            if (String.IsNullOrEmpty(uploader.TextForCancelled))
                uploader.TextForCancelled = "Upload Cancelled by User";
           
             
        }
        protected override void Render(HtmlTextWriter writer)
        {
            if (!this.DesignMode)
                sm.RegisterScriptDescriptors(this);

            base.Render(writer);
        }

        protected IEnumerable<ScriptDescriptor> GetScriptDescriptors()
        {
            ScriptControlDescriptor descriptor = new ScriptControlDescriptor("MikeKappel.Com.Uploader.ProgressBar", this.ClientID);
            descriptor.AddProperty("Guid", uploader.ID);
            descriptor.AddProperty("Name", uploader.Name);
            descriptor.AddProperty("ControlId", uploader.ClientID);

            descriptor.AddProperty("UrlOfThumbnail", Core.GetUrlOfThumbnail(uploader.ID));
            descriptor.AddProperty("UrlOfProgress", Core.GetUrlOfProgress(uploader.ID));
            descriptor.AddProperty("UrlOfCancel", Core.GetUrlOfCancel(uploader.ID));
            descriptor.AddProperty("UrlOfImage", Core.GetUrlOfImage(uploader.ID));
            descriptor.AddProperty("UrlOfForm", Core.GetUrlOfForm(uploader.ID));
            descriptor.AddProperty("ImageKey", Core.ImageKey);
            yield return descriptor;
        }

        protected IEnumerable<ScriptReference> GetScriptReferences()
        {
            yield return new ScriptReference("MikeKappel.Com.Uploader.js", this.GetType().Assembly.FullName);
        }
        
        protected override void CreateChildControls()
        {
            if (Width.IsEmpty)
                throw new Exception("Width property is required for ProgressControl " + this.ID);

            if (Height.IsEmpty)
                throw new Exception("Height property is required for ProgressControl " + this.ID);

            uploader.Width = (this.Width.IsEmpty) ? 300 : (Int32)this.Width.Value;
            uploader.Height = (this.Height.IsEmpty) ? 200 : (Int32)this.Height.Value;

            Panel progressContainer = new Panel();
            if (String.IsNullOrEmpty(this.CssOuterUrl))
            {
                this.CssOuterUrl = Page.ClientScript.GetWebResourceUrl(this.GetType(), "MikeKappel.Com.DefaultOuterStyle.css");
                progressContainer.Style.Add("width", uploader.Width.ToString() + "px");
                progressContainer.Style.Add("height", "10px");
            }
            this.Controls.Add(progressContainer);
            progressContainer.CssClass = this.CssClass + "ProgressContainer";

            Panel progressBar = new Panel();
            progressContainer.Controls.Add(progressBar);
            progressBar.CssClass = this.CssClass + "ProgressBar";

            iframe = new HtmlGenericControl("iframe");
            this.Controls.Add(iframe);
            iframe.Attributes.Add("class", this.CssClass);
            iframe.Attributes.Add("name", "ifrm_" + this.UniqueID);
            iframe.Attributes.Add("frameborder", "0");
            iframe.Attributes.Add("scrolling", "no");
            iframe.Style.Add("width", Width.ToString());
            iframe.Style.Add("height", Height.ToString());
            iframe.Attributes.Add("width", Width.ToString());
            iframe.Attributes.Add("height", Height.ToString());
        }
        IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
        {
            return GetScriptReferences();
        }

        IEnumerable<ScriptDescriptor> IScriptControl.GetScriptDescriptors()
        {
            return GetScriptDescriptors();
        }
        public void SaveTo(out Byte[] image, out String mime)
        {
            image = uploader.Content;
            mime = uploader.Mime;
            uploader = null;
            Core.Dispose(uploader.ID);
        }
        private String CurrentFrameUrl(){
            return (uploader.Status == uploadStatus.Completed) ? Core.GetUrlOfSubmission(uploader.ID) : Core.GetUrlOfForm(uploader.ID);
        }
    }
}